import { _decorator, Node, Label, find, Sprite, Animation } from 'cc';
import { BasePanel } from '../../../../scripts/libs/ui/BasePanel';
import { ReactiveProperty } from '../../../../scripts/libs/rxjs/cc3/ReactiveProperty';
import { StageInfo } from '../../game/basic';
import { Button } from 'cc';
import { BindButton } from '../../../../scripts/libs/rxjs/cc3/BindButton';
import { udm } from '../../../../scripts/managers/UserDataManager';
import { concat, forkJoin, Observable, of, Subscription, subscribeOn } from 'rxjs';
import { am } from '../../../../scripts/managers/AudioManager';
import { IntervalStartNow, Timer } from '../../../../scripts/libs/rxjs/cc3/CreatorSchedule';
import { TweenToStart } from '../../../../scripts/libs/rxjs/cc3/TweenStart';
import { UIOpacity } from 'cc';
import { DevConfig } from '../../../../scripts/managers/DevConfig';
import { thinking_sdk_m } from '../../../../scripts/managers/SDK/ThinkingCocosSDKManager';
import { gm } from '../../../../scripts/managers/GameManager';
import { lm } from '../../LobbyManager';
import { adsm } from '../../../../scripts/managers/AdsManager';
import { nc } from '../../../../scripts/libs/rxjs/NotificationCenter';
import { view } from 'cc';
import { linear } from '../../../../scripts/libs/utils/math';
import { StringTools } from '../../../../scripts/libs/utils/StringTools';
import { nullifySubscription } from '../../../../scripts/libs/rxjs/utils';
import { MergeASAP } from '../../../../scripts/libs/rxjs/cc3/Merge';
import { AnimationPlay } from '../../../../scripts/libs/rxjs/cc3/AnimationPlay';
import { instantFunc } from '../../../../scripts/libs/rxjs/cc3/CommonObservable';
import { Vec3 } from 'cc';
import { ResourceHelper } from '../../ResourceHelper';
import { ParticleSystem2D } from 'cc';
import { v3 } from 'cc';
import { UITransform } from 'cc';
import { BurstComponent } from '../../../model3d/_caidai/BurstComponent';
const { ccclass, property } = _decorator;

@ccclass('GameWinPanel')
export class GameWinPanel extends BasePanel {

    stageInfo = ReactiveProperty.Create<StageInfo>(null);

    @property(Node)
    bgNode: Node = null;

    @property(Node)
    mainNode: Node = null;

    @property(Node)
    boardNode: Node = null;

    @property(Button)
    adsButton: Button = null;

    @property(Label)
    adsCoinLabel: Label = null;

    @property(Button)
    nextButton: Button = null;

    @property(Label)
    nextCoinLabel: Label = null;

    // @property(ProgressBar)
    // chestProgressBar: ProgressBar = null;

    // @property(Label)
    // chestLabel: Label = null;

    @property(Node)
    buttonsNode: Node = null;

    @property(Label)
    coinCountLabel: Label = null;

    @property(Node)
    coinNode: Node = null;

    @property(Node)
    fxContainer: Node = null;

    coinValue = ReactiveProperty.Create(0);

    willBind(): void {
        gm.currentAdsType.value = 'AdWinDouble';
        gm.currentAdsOpenUI.value = 'GameWinPanel';
        gm.currentInterstitialAdsType.value = 'AdWin';
        this.bgNode.getComponent(UIOpacity).opacity = 0;
        this.mainNode.getComponent(UIOpacity).opacity = 0;
        this.adsCoinLabel.string = `${DevConfig.COIN_COMPLETED_EARN_ADS}`;
        this.nextCoinLabel.string = `${DevConfig.COIN_COMPLETED_EARN}`;
        this.adaptive();

        this.buttonsNode.active = false;
        this.buttonsNode.getComponent(UIOpacity).opacity = 0;

        lm.gameWinPanelOpened.value = true;
        gm.bgmFadeReason.delete('pre_win_panel');
    }

    useObserves() {
        return [
            BindButton(this.nextButton).subscribe(this.nextButtonClicked.bind(this)),
            BindButton(this.adsButton).subscribe(this.adsButtonClicked.bind(this)),
            this.stageInfo.subscribe(this.refresh.bind(this)),
            this.waiting.subscribePairWise(this.waitingChestChanged.bind(this)),
            this.coinValue.subscribe(this.refreshCoin.bind(this)),
            MergeASAP(udm.coin, gm.coinAnimatingFlags, udm.temp_coin_diff).subscribe(this.refreshCoinTarget.bind(this)),
            nc.subscribe('fly_coin_inc_value', this.flyCoinIncValue.bind(this)),
        ];
    }



    openPanelAnim(): Observable<any> {
        this.ensureUIOpacity().opacity = 255;
        am.playSfx({ clipName: `ab_lobby/Audio/sfx/LevelCompleted` });
        return concat(
            Timer(.3, this.node),
            forkJoin([
                TweenToStart(this.bgNode.getComponent(UIOpacity), 1, { opacity: 255 }, { easing: 'expoOut' }),
                TweenToStart(this.mainNode.getComponent(UIOpacity), 1, { opacity: 255 }, { easing: 'expoOut' })
            ]),
            instantFunc(() => {
                this.startRepeatStarBurst();
            })
        );
    }

    afterOpen(): Observable<string> {
        Timer(.1, this.node).subscribe(_ => {
            this.waiting.value = false;
        }).addTo(this.node);
        return of(null);
    }

    willClose(): Observable<string> {
        this.getComponentsInChildren(BurstComponent).forEach(_ => _.recycle());
        this.recycleAllStartBurst();
        return of(null);
    }

    onDestroyView(): void {
        nullifySubscription.call(this, '_sub_coin_shake');
        lm.gameWinPanelOpened.value = false;
    }

    _already_track_ads_show = false;
    waiting = ReactiveProperty.Create(true);

    adaptive() {
        let height = view.getVisibleSize().height;
        let scale = linear(1650, 2400, .7, 1, height);
        this.boardNode.setScale(scale, scale, scale);
    }

    refresh() {
        if (this.stageInfo.value == null) return;

        gm.lastWinStageNum.value = this.stageInfo.value.stageId; // 回主页后，需要利用此值进行自动弹窗

        // let { chestCurValue, chestMaxValue, flag } = udm.checkStageChestProgress(this.stageInfo.value);
        // this.chestLabel.string = `${chestCurValue} / ${chestMaxValue}`;
        // this.chestProgressBar.progress = chestCurValue / chestMaxValue;


        if (this.stageInfo.value.stageId >= DevConfig.REWARDEDAD_FROM_STAGE_NUM) {
            this.adsButton.node.active = true;
            if (!this._already_track_ads_show) {
                this._already_track_ads_show = true;
                thinking_sdk_m.requestTrack('Ads_Show', {
                    AdsType: gm.currentAdsType.value,
                    OpenUI: gm.currentAdsOpenUI.value,
                    IsNew: udm.isNew.value
                });
            }
        } else {
            this.adsButton.node.active = false;
        }

        // this.waiting.value = false;

        // if (udm.stageChest.value != null) {
        //     this.waitingChest.value = true;
        // this.chestProgressAnim().subscribe({
        //     complete: () => {
        //         ChestOpenPanel.StartProcess((panel: ChestOpenPanel) => {
        //             panel.stageInfo.value = this.stageInfo.value;
        //             panel.key.value = udm.stageChest.value;
        //         }).subscribe(_ => {

        //             let { chestCurValue, chestMaxValue, flag } = udm.checkStageChestProgress(udm.stageNum.value, false);
        //             this.chestLabel.string = `${chestCurValue} / ${chestMaxValue}`;
        //             this.chestProgressBar.progress = chestCurValue / chestMaxValue;

        //             this.waitingChest.value = false;
        //         }).addTo(this.node);
        //     }
        // });
        // } else {
        //     this.waitingChest.value = true;
        // this.chestProgressAnim().subscribe({
        //     complete: () => {
        //         this.waitingChest.value = false;
        //     }
        // }).addTo(this.node);
        // }
    }

    waitingChestChanged(pair: [boolean, boolean]) {
        if (!pair[0] && pair[1]) { // 进入等待
            this.buttonsNode.active = false;
            this.buttonsNode.getComponent(UIOpacity).opacity = 0;
        } else if (pair[0] && !pair[1]) { // 等待完毕
            this.buttonsNode.active = true;
            TweenToStart(this.buttonsNode.getComponent(UIOpacity), .2, { opacity: 255 }, { easing: 'quadOut' }).subscribe().addTo(this.node);
        }

    }

    // chestProgressAnim() {
    //     return new Observable(observer => {
    //         let { chestCurValue, chestMaxValue, flag } = udm.checkStageChestProgress(this.stageInfo.value.stageId);
    //         this.chestLabel.string = `${chestCurValue - 1} / ${chestMaxValue}`;
    //         this.chestProgressBar.progress = (chestCurValue - 1) / chestMaxValue;
    //         let _sub = concat(
    //             Timer(1.5, this.node),
    //             TweenToStart(this.chestProgressBar, .6, { progress: chestCurValue / chestMaxValue }, { easing: 'quadInOut' }),
    //             instantFunc(() => { this.chestLabel.string = `${chestCurValue} / ${chestMaxValue}`; }),
    //             Timer(.2, this.node),
    //         ).subscribe(TransparentPass(observer))
    //         return () => {
    //             if (_sub) _sub.unsubscribe();
    //         }
    //     });
    // }

    nextButtonClicked() {
        if (this.waiting.value) {
            // lm.frontTipShow('Waiting...');
            return;
        }
        udm.temp_coin_diff.value = null;

        // if (this.stageInfo.value.stageId >= DevConfig.DIRECT_START_LESSEQUAL_STAGE_NUM) {
        //     let coinIconNode = find('Layout/icon', this.nextButton.node)
        //     nc.post('fly_coins', { fromWorldPos: coinIconNode.worldPosition, count: DevConfig.COIN_COMPLETED_EARN });
        // }

        let coinIconNode = find('Layout/icon', this.nextButton.node)
        nc.post('fly_coins', { fromWorldPos: coinIconNode.worldPosition, count: DevConfig.COIN_COMPLETED_EARN, toWorldPos: this.coinNode.worldPosition });

        Timer(.7, this.node).subscribe(_ => {
            am.playSfx({ clipName: `ab_lobby/Audio/sfx/gold` });
        }).addTo(this.node);

        gm.coinAnimatingFlags.delete('over_anim');

        this.waiting.value = true;

        nc.post('clear_stage', {});

        gm.loadNextGameCommand.execute();

        Timer(2, this.node).subscribe(_ => {
            GameWinPanel.CloseProcess(null, 'next');
            adsm.tryShowInterstitialAds(this.stageInfo.value, 'AdWin'); // 展示插屏广告已经全部封装
            // this.waiting.value = false;
        }).addTo(this.node);

    }

    adsButtonClicked() {
        if (this.waiting.value) {
            // lm.frontTipShow('Waiting...');
            return;
        }
        thinking_sdk_m.requestTrack('Ads_Click', {
            AdsType: gm.currentAdsType.value,
            OpenUI: gm.currentAdsOpenUI.value,
            IsNew: udm.isNew.value
        });
        adsm.showRewardAds('stage_completed_double_reward').subscribe(_ => {
            if (_ == 'success') {
                thinking_sdk_m.requestTrack('Ads_Return', {
                    AdsType: gm.currentAdsType.value,
                    OpenUI: gm.currentAdsOpenUI.value,
                    IsNew: udm.isNew.value
                });

                // let hard = this.stageInfo.value.hard;

                this.mainNode.active = false;

                // Timer(2, this.node).subscribe(_ => {
                udm.coin.value += DevConfig.COIN_COMPLETED_EARN_ADS - DevConfig.COIN_COMPLETED_EARN;
                udm.save();

                thinking_sdk_m.requestTrack('Coins_Get', {
                    CoinNum: DevConfig.COIN_COMPLETED_EARN_ADS - DevConfig.COIN_COMPLETED_EARN,
                    coinall: udm.coin.value,
                    Type: 'LevelWinDouble',
                    Gift_Detail: 'Other',
                    IsNew: udm.isNew.value,
                    Level_ID: this.stageInfo.value.stageId,
                });

                udm.temp_coin_diff.value = null;

                if (this.stageInfo.value.stageId >= DevConfig.DIRECT_START_LESSEQUAL_STAGE_NUM) {
                    let coinIconNode = find('Layout/icon', this.nextButton.node)
                    nc.post('fly_coins', { fromWorldPos: coinIconNode.worldPosition, count: DevConfig.COIN_COMPLETED_EARN_ADS });
                }

                gm.coinAnimatingFlags.delete('over_anim');
                GameWinPanel.CloseProcess(null, 'next');
                // });

            }
        });
    }


    refreshCoin() {
        this.coinCountLabel.string = StringTools.toKDotString(Math.floor(this.coinValue.value));
    }

    _sub_coin_value_tween: Subscription = null;
    refreshCoinTarget() {
        if (udm.temp_coin_diff.value != null) {
            this._sub_coin_value_tween = TweenToStart(this.coinValue, .4, { value: this.coinValue.value + udm.temp_coin_diff.value }).subscribe();
            return;
        }
        if (gm.coinAnimatingFlags.size > 0) return;
        nullifySubscription.call(this, '_sub_coin_value_tween');
        this._sub_coin_value_tween = TweenToStart(this.coinValue, .4, { value: udm.coin.value }).subscribe();
    }

    _sub_coin_shake: Subscription = null;
    flyCoinIncValue(param: { value: number }) {
        this.coinValue.value += param.value;
        nullifySubscription.call(this, '_sub_coin_shake');
        this._sub_coin_shake = AnimationPlay(this.coinNode.getComponent(Animation), 'icon_shake').subscribe();
    }

    startRepeatStarBurst() {
        let fxTransform = this.fxContainer.getComponent(UITransform);
        IntervalStartNow(.5, this.node).subscribe(_ => {
            let x = linear(0, 1, -fxTransform.width / 2, fxTransform.width / 2, Math.random());
            let y = linear(0, 1, -fxTransform.height / 2, fxTransform.height / 2, Math.random());
            this.genStarBurst(v3(x, y, 0));
        }).addTo(this.node);
        IntervalStartNow(.7, this.node).subscribe(_ => {
            let x = linear(0, 1, -fxTransform.width / 2, fxTransform.width / 2, Math.random());
            let y = linear(0, 1, -fxTransform.height / 2, fxTransform.height / 2, Math.random());
            this.genStarBurst(v3(x, y, 0));
        }).addTo(this.node);
    }

    genStarBurst(localPos: Vec3) {
        let starBurstNode = ResourceHelper.StarBurstPool.getNode();
        nullifySubscription.call(starBurstNode, '_sub');
        starBurstNode.setParent(this.fxContainer);
        starBurstNode.setPosition(localPos);
        let anim = starBurstNode.getChildByName('circle').getComponent(Animation)
        AnimationPlay(anim, 'circle').subscribe();
        let p2d = starBurstNode.getComponentInChildren(ParticleSystem2D);
        p2d.resetSystem();
        let _sub = concat(
            Timer(.1, starBurstNode),
            instantFunc(() => {
                p2d.stopSystem();
            }),
            Timer(.4, starBurstNode),
        ).subscribe({
            complete: () => {
                ResourceHelper.StarBurstPool.putNode(starBurstNode);
            }
        });
        starBurstNode.attr({ _sub });
    }

    recycleAllStartBurst() {
        this.fxContainer.children.map(_ => _).forEach(_ => {
            nullifySubscription.call(_, '_sub');
            ResourceHelper.StarBurstPool.putNode(_);
        });
    }
}

